package com.casstime.ec.cloud.discount.restful;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.casstime.commons.service.exception.HttpMessageException;
import com.casstime.commons.utils.JsonUtil;
import com.casstime.ec.cloud.clients.feign.product.ProductClient;
import com.casstime.ec.cloud.discount.client.Companyv2Client;
import com.casstime.ec.cloud.discount.client.Userv2Client;
import com.casstime.ec.cloud.discount.dao.amount.AmountPromotionFlowingMapper;
import com.casstime.ec.cloud.discount.dao.amount.AmountPromotionUpdateRecordMapper;
import com.casstime.ec.cloud.discount.model.AmountCalcResp;
import com.casstime.ec.cloud.discount.model.DiscountRuleParam;
import com.casstime.ec.cloud.discount.rule.DiscountPolicyRule;
import com.casstime.ec.cloud.discount.services.BusinessDAOService;
import com.casstime.ec.cloud.discount.services.DiscountDAOService;
import com.casstime.ec.cloud.discount.util.CassAssert;
import com.casstime.ec.cloud.service.GenericService;
import com.casstime.ec.cloud.service.amountPromotion.DiscountService;
import com.casstime.ec.cloud.spi.PagedModels;
import com.casstime.ec.cloud.user.spi.models.Company;
import com.casstime.ec.cloud.user.spi.models.User;
import com.casstime.ec.cloud.values.amountPromotion.AmountPromotion;
import com.casstime.ec.cloud.values.amountPromotion.AmountPromotionBrandCategoryVO;
import com.casstime.ec.cloud.values.amountPromotion.AmountPromotionCompany;
import com.casstime.ec.cloud.values.amountPromotion.AmountPromotionConfig;
import com.casstime.ec.cloud.values.amountPromotion.AmountPromotionFlowing;
import com.casstime.ec.cloud.values.amountPromotion.AmountPromotionFlowingRequest;
import com.casstime.ec.cloud.values.amountPromotion.AmountPromotionQueryRequest;
import com.casstime.ec.cloud.values.amountPromotion.AmountPromotionRequest;
import com.casstime.ec.cloud.values.amountPromotion.AmountPromotionUpdateRecord;
import com.casstime.ec.cloud.values.amountPromotion.OrderProductParam;
import com.casstime.ec.cloud.values.amountPromotion.OrderPromotionParam;
import com.casstime.ec.cloud.values.amountPromotion.OrderRequest;
import com.casstime.ec.cloud.values.amountPromotion.enums.DiscountConfigValueEnum;
import com.casstime.ec.cloud.values.business.SupplierGarageBusiness;
import com.casstime.ec.cloud.values.product.info.ProductFull;
import com.casstime.ec.cloud.values.product.param.ProductIdRequest;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * ClassName: DiscountServiceImpl 
 * Function: (金额促销实现类)
 * Reason: ADD REASON(可选).
 *  
 * @author wu.chen 
 * 2018年2月26日 上午11:02:13
 * @version   
 * @since JDK 1.8
 */
@RestController
public class DiscountServiceRest extends GenericService implements DiscountService {
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());	
	
	@Autowired
	private DiscountDAOService discountDAOService;
	
	@Autowired
	private AmountPromotionUpdateRecordMapper updateRecordMapper;
	
	@Autowired
	private Userv2Client userv2Client;
	
	@Autowired
	private Companyv2Client companyv2Client;
	
	@Autowired
	private DiscountPolicyRule discountPolicyRule;
	
	@Autowired
	private ProductClient productClient;
	
	@Autowired 
	private BusinessDAOService businessDAOService;
	
	@Autowired
	private AmountPromotionFlowingMapper amountPromotionFlowingMapper;

	
	@Override
	public int addOrUpdateAmountPromotion(@RequestBody AmountPromotion amountPromotion,
			@RequestParam("userLoginId") String userLoginId, @RequestParam("companyId") String companyId)
					throws Exception {
		User user = null;
		SimpleDateFormat simpleformat = new SimpleDateFormat("yyyyMMddHHmmss");
		amountPromotion.setEffectDate(simpleformat.parse(simpleformat.format(amountPromotion.getEffectDate())));
		amountPromotion.setExpireDate(simpleformat.parse(simpleformat.format(amountPromotion.getExpireDate())));
		if (StringUtils.isNotBlank(userLoginId)) {
			user = userv2Client.getUser(userLoginId);
		} else {
			return 0;
		}
		if (StringUtils.isNotBlank(amountPromotion.getId())) {
			return discountDAOService.updateAmountPromotion(amountPromotion, user);
		} else {
			return discountDAOService.addAmountPromotion(amountPromotion, user);
		}
	}

	@Override
	public AmountPromotion findAmountPromotion(@PathVariable("promotionId") String promotionId) throws Exception {
		return discountDAOService.findAmountPromotion(promotionId);
	}

	@Override
	public PagedModels<AmountPromotionUpdateRecord> listAmountPromotionRecordById(@PathVariable("promotionId") String promotionId,
			   @RequestParam("pageSize") Integer pageSize,
			   @RequestParam("pageNum") Integer pageNum) throws Exception {
		Page<AmountPromotionUpdateRecord> pagedResult = PageHelper.startPage(pageNum, pageSize);
		updateRecordMapper.listAmountPromotionRecords(promotionId);
        return super.toPagedModels(pagedResult);
	}

	@Override
	public Map<String, List<AmountPromotion>> queryDiscountPolicys(@RequestBody AmountPromotionQueryRequest queryRequest)
			throws Exception {
		CassAssert.isNotNull(queryRequest.getCompanyId(), 404, "公司ID不能为空");
		CassAssert.isNotNull(queryRequest.getUserLoginId(), 404, "当前登陆用户不能为空");
		if (CollectionUtils.isEmpty(queryRequest.getProductIds())) {
			logger.error("商品列表不能为空");
			throw new HttpMessageException(404, "商品列表不能为空");
		}
		long start = System.currentTimeMillis();
		List<DiscountRuleParam> ruleParams = assembleParams(queryRequest);
		if (CollectionUtils.isEmpty(ruleParams)) {
			return Maps.newHashMap();
		}
		logger.info("查询满减活动 查询条件耗时：{}", System.currentTimeMillis() - start);
		List<String> storeIds = ruleParams.stream().map(DiscountRuleParam::getProductStoreId).distinct().collect(Collectors.toList());
		List<AmountPromotion> promotions = discountDAOService.listAvailableAmountPromotions(storeIds, queryRequest.getPlatform());
		List<String> areaNeedStoreIds = Lists.newArrayList();
		
		for (AmountPromotion promotion : promotions) {
			for (AmountPromotionConfig config : promotion.getPromotionConfigs()) {
				if (DiscountConfigValueEnum.AREA_LIMIT.getIndex().equals(config.getConfigType())
						&& DiscountConfigValueEnum.AREA_LIMIT_DEFAULT.getIndex().equals(config.getConfigValue())) {
					areaNeedStoreIds.add(promotion.getProductStoreId());
				}
			}
		}
		logger.info("查询满减活动 查询配置耗时：{}", System.currentTimeMillis() - start);
//		Map<String, StoreQuoteArea> areaMap = getQuoteAreaByStoreIds(areaNeedStoreIds);
//		logger.info("查询满减活动 查询供应商区域耗时：{}", System.currentTimeMillis() - start);
		Map<String, List<AmountPromotion>> retMap = 
				discountPolicyRule.getDiscountPolicys(ruleParams, promotions, queryRequest.getCompanyId());
		
		logger.info("查询满减活动总耗时：{}", System.currentTimeMillis() - start);
		return retMap;
	}
	
	List<DiscountRuleParam> assembleParams(AmountPromotionQueryRequest queryRequest) {
		List<DiscountRuleParam> retParams = Lists.newArrayList();
		List<String> geoIds = new ArrayList<>();
		try {
			geoIds.add("CHN");
			Company company = companyv2Client.getCompanyById(queryRequest.getCompanyId());
			if (StringUtils.isNotBlank(company.getCityGeoId())) {
				geoIds.add(company.getCityGeoId());
			}
			if (StringUtils.isNotBlank(company.getProvinceGeoId())) {
				geoIds.add(company.getProvinceGeoId());
			}
		} catch (Exception e) {
			logger.error("查询公司失败 companyId = {}", queryRequest.getCompanyId(), e);
		}
		
		ProductIdRequest pidq = new ProductIdRequest();
		pidq.setProductIds(queryRequest.getProductIds());
		pidq.setUserLoginId(queryRequest.getUserLoginId());
		pidq.setResultColumn(Lists.newArrayList("BASE_CATAGORY"));
		Map<String, ProductFull> mapProduct = Maps.newHashMap();
		try {
			mapProduct = productClient.getProductsByIdsV2(pidq);
		} catch (Exception e1) {
			logger.error("获取商品信息失败 req = {}", JsonUtil.serializer(pidq), e1);
		}
		
		List<String> orderedStoreIds = Lists.newArrayList();
		List<SupplierGarageBusiness> stores = businessDAOService.listSupplierGarageBusiness(queryRequest.getCompanyId());
		if (CollectionUtils.isNotEmpty(stores)) {
			orderedStoreIds = stores.stream().map(SupplierGarageBusiness::getProductStoreId).collect(Collectors.toList());
		}
		
		for (String productId : queryRequest.getProductIds()) {
			DiscountRuleParam param = new DiscountRuleParam();
			param.setId(productId);
			param.setProductId(productId);
			param.setGeoIds(geoIds);
			if (mapProduct.containsKey(productId)) {
				param.setProductStoreId(mapProduct.get(productId).getProductInfo().getProductStoreId());
				param.setBrandId(mapProduct.get(productId).getProductInfo().getBrandName());
				if (mapProduct.get(productId).getBaseCatagory() != null) {
					param.setCategoryName(mapProduct.get(productId).getBaseCatagory().getParentItemName());
				}
			}
			if (StringUtils.isNotBlank(param.getProductStoreId())) {
				if (orderedStoreIds.contains(param.getProductStoreId())) {
					param.setCustomerType(DiscountConfigValueEnum.CUSTOMER_OLD.getIndex());
				} else {
					param.setCustomerType(DiscountConfigValueEnum.CUSTOMER_NEW.getIndex());
				}
			}
			retParams.add(param);
		}
		
		return retParams;
	}

	@Override
	public PagedModels<AmountPromotion> listAmountPromotionStoreId(@PathVariable("productStoreId") String productStoreId,
			   @RequestParam("pageSize") Integer pageSize,
			   @RequestParam("pageNum") Integer pageNum,
			   @RequestBody AmountPromotionRequest request) throws Exception {
		if (StringUtils.isNotBlank(request.getCustomerType()) && request.getCustomerType().equals(DiscountConfigValueEnum.CUSTOMER_ALL.getIndex())) {
			request.setCustomerType(null);
		}
		if (StringUtils.isNotBlank(request.getFullCutType()) && request.getFullCutType().equals(DiscountConfigValueEnum.FULLCUT_ALL.getIndex())) {
			request.setFullCutType(null);
		}
		if (StringUtils.isNotBlank(request.getPlatformType()) && request.getPlatformType().equals(DiscountConfigValueEnum.PLATFORM_ALL.getIndex())) {
			request.setPlatformType(null);
		}
		if (StringUtils.isNotBlank(request.getPromotionStatus())
				&& request.getPromotionStatus().equals(DiscountConfigValueEnum.STATUS_ALL.getIndex())) {
			request.setPromotionStatus(null);
		}
        return super.toPagedModels(discountDAOService.listAmountPromotionStoreId(productStoreId, pageSize, pageNum, request));
	}

	@Override
	public int stopAmountPromotion(@PathVariable("promotionId") String promotionId,
			@RequestParam("userLoginId") String userLoginId) throws Exception {
		User user = null;
		if (StringUtils.isNotBlank(userLoginId)) {
			user = userv2Client.getUser(userLoginId);
		} else {
			return 0;
		}
		return discountDAOService.stopAmountPromotion(promotionId, user);
	}
	
//	private Map<String, StoreQuoteArea> getQuoteAreaByStoreIds(List<String> productStoreIds) {
//		Map<String, StoreQuoteArea> retMap = Maps.newHashMap();
//		List<String> areaNeedCompanyIds = Lists.newArrayList();
//		Map<String, String> storeId2CompayId = Maps.newHashMap();
//		try {
//			if (CollectionUtils.isNotEmpty(productStoreIds)) {
//				List<Company> companys = companyv2Client.listCompaniesByCodes(productStoreIds);
//				if (companys != null) {
//					for (Company company : companys) {
//						storeId2CompayId.put(company.getProductStoreId(), company.getCompanyId());
//						areaNeedCompanyIds.add(company.getCompanyId());
//					}
//				}
//			}
//		} catch (Exception e) {
//			logger.error("通过店铺Id获取公司Id失败 storeIds = {}", JsonUtil.serializer(productStoreIds), e);
//		}
//		
//		try {
//			if (CollectionUtils.isNotEmpty(areaNeedCompanyIds)) {
//				List<StoreQuoteArea> areas = quoteClient.getStoreQuoteArea(areaNeedCompanyIds);
//				if (areas != null) {
//					for (StoreQuoteArea area : areas) {
//						retMap.put(area.getStoreId(), area);
//					}
//				}
//			}
//		} catch (Exception e) {
//			logger.error("获取店铺报价区域失败 storeIds = {}", JsonUtil.serializer(areaNeedCompanyIds), e);
//		}
//		
//		return retMap;
//	}

	@Override
	public Map<String, OrderPromotionParam> orderQueryDiscount(@RequestBody OrderRequest orderRequest) throws Exception {
		
		CassAssert.isNotNull(orderRequest.getCompanyId(), 404, "公司ID不能为空");
		CassAssert.isNotNull(orderRequest.getUserLoginId(), 404, "当前登陆用户不能为空");
		CassAssert.isNotNull(orderRequest.getOrderParams(), 404, "订单商品列表不能为空");
		Map<String, AmountPromotion> needPromotionMap = this.validAmountPromotionExist(orderRequest);
		Map<String, OrderPromotionParam> retMap = Maps.newHashMap();
		for (OrderPromotionParam param : orderRequest.getOrderParams()) {
			if (CollectionUtils.isEmpty(param.getProductPrams()) || !param.isAvailable()) {
				retMap.put(param.getAmountPromotionId(), param);
				continue;
			}
			BigDecimal totalPrice = BigDecimal.ZERO;
			for (OrderProductParam productItem : param.getProductPrams()) {
				totalPrice = totalPrice.add(productItem.getProductPrice().multiply(new BigDecimal(productItem.getProductNumber())));
			}
			AmountPromotion promotion = needPromotionMap.get(param.getAmountPromotionId());
			AmountCalcResp calcResp = discountPolicyRule.calcCutFormProduct(promotion, totalPrice);
			param.setCurrentPromotionAmount(calcResp.getCurrentAmount());
			param.setNextPromotionAmount(calcResp.getNextAmount());
			if (calcResp.getTotalCut() > 0) {
				BigDecimal actTotalCut = discountPolicyRule.doCalcPerCut(calcResp.getTotalCut(), param.getProductPrams());
				if (actTotalCut.compareTo(new BigDecimal(calcResp.getTotalCut())) > 0) {
					logger.error("满减计算异常，终止订单金额计算 products = {} , totalCut = {}",
							JsonUtil.serializer(param.getProductPrams()), calcResp.getTotalCut());
					throw new HttpMessageException(500, "满减计算异常，终止订单金额计算");
				}
				param.setDiscCountAmount(actTotalCut);
				retMap.put(param.getAmountPromotionId(), param);
			} else {
				param.setAvailable(false);
				param.setReason("订单金额不满足条件");
				retMap.put(param.getAmountPromotionId(), param);
			}
		}
		return retMap;
	}
	
	private Map<String, AmountPromotion> validAmountPromotionExist(OrderRequest orderRequest) {
		Map<String, AmountPromotion> retMap = Maps.newHashMap();
		AmountPromotionQueryRequest queryRequest = new AmountPromotionQueryRequest();
		queryRequest.setCompanyId(orderRequest.getCompanyId());
		queryRequest.setUserLoginId(orderRequest.getUserLoginId());
		queryRequest.setPlatform(orderRequest.getPlatform());
		List<String> productIds = Lists.newArrayList();
		for (OrderPromotionParam param : orderRequest.getOrderParams()) {
			if (param.getProductPrams() == null) {
				continue;
			}
			for (OrderProductParam product : param.getProductPrams()) {
				if (!productIds.contains(product.getProductId())) {
					productIds.add(product.getProductId());
				}
			}
		}
		queryRequest.setProductIds(productIds);
		Map<String, List<AmountPromotion>> tempFindMap = null;
		try {
			tempFindMap = this.queryDiscountPolicys(queryRequest);
		} catch (Exception e) {
			tempFindMap = Maps.newHashMap();
		}
		
		for (OrderPromotionParam param : orderRequest.getOrderParams()) {
			param.setAvailable(false);
			if (param.getProductPrams() == null) {
				continue;
			}
			for (OrderProductParam product : param.getProductPrams()) {
				List<AmountPromotion> tempAmountList = null;
				if (tempFindMap.containsKey(product.getProductId())) {
					tempAmountList = tempFindMap.get(product.getProductId());
				} else {
					param.setAvailable(false);
					param.setReason("部分商品满减活动不存在或者已经结束");
					break;
				}
				boolean existFlag = false;
				for (AmountPromotion amount : tempAmountList) {
					if (amount.getId().equals(param.getAmountPromotionId())) {
						existFlag = true;
						param.setAvailable(true);
						retMap.put(param.getAmountPromotionId(), amount);
						break;
					}
				}
				if (!existFlag) {
					param.setAvailable(false);
					param.setReason("部分商品满减活动不存在或者已经结束");
					break;
				}
			}
		}
		
		return retMap;
	}

	@Override
	public PagedModels<AmountPromotionFlowing> listAmountPromotionFlowStoreId(@PathVariable("productStoreId") String productStoreId,
			   @RequestParam("pageSize") Integer pageSize,
			   @RequestParam("pageNum") Integer pageNum,
			   @RequestBody AmountPromotionFlowingRequest request) throws Exception {
			if (StringUtils.isNotBlank(request.getFullCutType()) && request.getFullCutType().equals(DiscountConfigValueEnum.FULLCUT_ALL.getIndex())) {
				request.setFullCutType(null);
			}
			if (StringUtils.isNotBlank(request.getPlatformType()) 
					&& request.getPlatformType().equals(DiscountConfigValueEnum.PLATFORM_ALL.getIndex())) {
				request.setPlatformType(null);
			}
			Page<AmountPromotionFlowing> pagedResult = PageHelper.startPage(pageNum, pageSize);
			amountPromotionFlowingMapper.listAmountPromotionFlowing(productStoreId, request);
			return super.toPagedModels(pagedResult);
	}

	@Override
	public List<AmountPromotionCompany> listAmountPromotionCompanyBystoreId(@PathVariable("productStoreId") String productStoreId) throws Exception {
		List<AmountPromotionCompany> list  = amountPromotionFlowingMapper.listAmountPromotionCompanyBystoreId(productStoreId);
		if (CollectionUtils.isEmpty(list)) {
			return  Lists.newArrayList();
		}
		return list;
	}

	/**
	 * validBrandAndCategory:(满减后台验证接口).<br/>  
	 * @param productStoreId
	 * @param startDate
	 * @param endDate
	 * @param brandIds
	 * @param categoryIds
	 * @return
	 * @throws Exception
	 * @author 徐彪
	 * @date 2018年3月24日 下午1:53:03
	 */
	@Override
	public List<Map<String, String>> validBrandAndCategory(@RequestBody AmountPromotionBrandCategoryVO vo) throws Exception {
		String productStoreId = vo.getProductStoreId();
		Date startDate = vo.getStartDate();
		Date endDate = vo.getEndDate();
		if (StringUtils.isEmpty(productStoreId)) {
			return Lists.newArrayList();
		} else {
			return discountDAOService.validBrandAndCategory(productStoreId, startDate, endDate);
		}
	}

}
